import __DB__               from '../db/index.js';
import __formate__          from '../formate/index.js';
import __tool__             from '../tool/index.js';
import __canvas__           from '../canvas/index.js';
import __customEvent__      from '../customEvent/index.js';

class automaticClass{
    constructor(){
        this.canvas             = null;
        this.isDraw             = false;
        this.startId          = "";
        this.endId            = "";
        this.start              = null;
        this.end                = null;
        this.nodes              = [];
        this.paths              = [];
        this.pathsOnlyName      = [];
        this.lineCanvas         = null;
        this.guideLine          = null;
        this.inlineIsChecked    = false;
        this.checkedColor       = "#FFC800";
    }

    // 重置automatic.reset
    reset(res){
        this.paths = [];
        if(this.canvas)this.canvas.innerHTML = "";
        
        let nodes = res.nodes.filter(item=>{
            return item.show===true;
        })
        // pathsName 需要保存
        this.pathsOnlyName = this.pathsOnlyName.filter(el=>{
            if(!__DB__.has(el.s) || !__DB__.has(el.e))return false;
            if(!__DB__.has(el.s).flip !== !__DB__.has(el.e).flip)return false;
            if(__DB__.has(el.s).pid === el.e || __DB__.has(el.e).pid === el.s)return false;
            if(__DB__.has(el.s).nodeType === "free" || __DB__.has(el.e).nodeType === "free")return false;

            this.startId  = el.s;
            this.endId    = el.e;
            
            this.contect({
                nodes       : nodes,
                canvas      : document.getElementById('automaticConnection'),
                isChecked   : el.isChecked||false,
            });

            return true;
        })
    }

    // 连线
    contect(res){
        document.onmousemove    = null;
        document.onmousedown    = null;
        
        this.nodes                  = __DB__.getAllNodes();
        this.canvas                 = res.canvas||null;
        this.lineCanvas             = document.getElementById("svgDirection");
        this.lineCanvas.innerHTML   = "";
        this.isDraw                 = false;

        let startData               = __DB__.get(this.startId);
        let endData                 = __DB__.get(this.endId);
        
        if(!startData.show || !endData.show)return;
        if(startData.pid === this.endId)return;
        if(endData.pid === this.startId)return;
        if(startData.flip !== endData.flip)return;

        this.start      = {
            id:startData.id,
            init:startData.node.init
        };
        this.end        = {
            id:endData.id,
            init:endData.node.init
        };

        this.inlineIsChecked = res.isChecked||false;

        this.direction();

    }

    // 删除关联线
    delLine(s,e){
        this.pathsOnlyName = this.pathsOnlyName.filter(item=>{
            return !(item.s === s && item.e === e);
        })

        this.reset({
            nodes:this.nodes
        });
    }

    // 方向
    direction(){
        let start       = this.start.init;
        let end         = this.end.init;
        let startName   = this.startId;
        let endName     = this.endId;
        let mid1        = start.point.mid;
        let mid2        = end.point.mid;
        let x1          = mid1[0],
            y1          = mid1[1],
            x2          = mid2[0],
            y2          = mid2[1];
        
        // 自下而右上
        if(x1 < x2 && y1 > y2){
            next_x_d_y_t_l.call(this);
            return;
        }

        // 自下而左上
        if(x1 > x2 && y1 > y2){
            next_x_d_y_t_r.call(this);
            return;
        }

        // 自上而右下
        if(x1 < x2 && y1 < y2){
            next_x_t_y_d_l.call(this);
            return;
        }

        // 自上而左下
        if(x1 > x2 && y1 < y2){
            next_x_t_y_d_r.call(this);
            return;
        }

        // 自下而上
        if(x1 === x2 && y1 > y2){
            next_x_d_y_t_c.call(this);
            return;
        }

        // 自上而下
        if(x1 === x2 && y1 < y2){
            next_x_t_y_d_c.call(this);
            return;
        }

        // 自左而右
        if(x1 < x2 && y1 === y2){
            next_x_l_y_r.call(this);
            return;
        }

        // 自右而左
        if(x1 > x2 && y1 === y2){
            next_x_r_y_l.call(this);
            return;
        }

        // 自下而右上
        function next_x_d_y_t_l(){
            let lineSegments = [];

            let s = start.point.ab,
                e = end.point.cd;

            let x1 = s[0],
                y1 = s[1],
                x2 = e[0],
                y2 = e[1];
            
            let path1 = [s,[x1,y1 - 10]];
            let path2 = [path1[1],[x2,y1 - 10]];
            let path3 = [path2[1],e];

            lineSegments = [path1,path2,path3];
            lineSegments = findToutch.call(this,lineSegments);

            if(!lineSegments || lineSegments.length === 0)return;
            let nowLine = lineSegments.map(el=>{
                return {
                    x1:el[0][0],
                    y1:el[0][1],
                    x2:el[1][0],
                    y2:el[1][1],
                }
            });

            let signLine = true;
            for(let el of this.paths){
                if(el.ids[0] === startName && el.ids[1] === endName){
                    signLine = false;
                    break;
                }
            }

            if(signLine){
                this.paths.push({
                    isChecked:this.inlineIsChecked,
                    id:startName+endName,
                    ids:[startName,endName],
                    path:nowLine
                });
                this.pathsOnlyName.push({
                    s:startName,
                    e:endName
                });
                this.drawLine();
            }

            function findToutch(arr){
                let nodes = this.nodes.filter(item=>{
                    return item.id !== startName && item.id !== endName;
                });
            
                let line1 = arr[0],
                    line2 = arr[1],
                    line3 = arr[2];
                
                let newLines = toutchFor.call(this);

                let cd = __DB__.get(endName).node.init.point.cd;
                if(newLines[2][1][0] > cd[0]){
                    line3[1] = [line3[1][0],line3[1][1]]
                    let line4 = [
                        newLines[2][1],
                        [cd[0],cd[1] + 10]
                    ];
                    let line5 = [
                        line4[1],
                        cd
                    ];
                    newLines.push(line4);
                    newLines.push(line5);
                }
            
                return newLines;
            
                function toutchFor(){
                    for(let k in nodes){
                        let el = nodes[k];
                        let down = [el.node.init.point.d,el.node.init.point.c],
                            left = [el.node.init.point.a,el.node.init.point.d];
                        
                        let sgin_down = this.segmentsIntr(line3[0],line3[1],down[0],down[1]);
                        let sgin_left = this.segmentsIntr(line2[0],line2[1],left[0],left[1]);
                        
                        if(sgin_down){
                            touchDown.call(this,el.id)
                            break
                        }
            
                        if(sgin_left){
                            touchLeft.call(this,el.id)
                            break
                        }
                        
                    }
            
                    return [line1,line2,line3];
                }
            
                function touchDown(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let c_the  = theDiv.node.init.point.c;
                    let cd_end = endDiv.node.init.point.cd;
            
                    line2 = [line2[0],[c_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], cd_end[1] +10]];
            
                    toutchFor.call(this);
                }
            
                function touchLeft(id){
                    line1 = [
                        line1[0],
                        [line1[1][0],parseFloat(line1[1][1]) - 10]
                    ];
                    line2 = [
                        line1[1],
                        [line2[1][0], line2[1][1] - 10]
                    ];
                    line3 = [line2[1],line3[1]];
            
                    toutchFor.call(this);
                }
            }
        }

        // 自下而左上
        function next_x_d_y_t_r(){
            let lineSegments = [];

            let s = start.point.ab,
                e = end.point.cd;

            let x1 = s[0],
                y1 = s[1],
                x2 = e[0],
                y2 = e[1];
            
            let path1 = [s,[x1,y1 - 10]];
            let path2 = [path1[1],[x2,y1 - 10]];
            let path3 = [path2[1],e];

            lineSegments = [path1,path2,path3];
            lineSegments = findToutch.call(this,lineSegments);

            if(!lineSegments || lineSegments.length === 0)return;
            let nowLine = lineSegments.map(el=>{
                return {
                    x1:el[0][0],
                    y1:el[0][1],
                    x2:el[1][0],
                    y2:el[1][1],
                }
            });

            let signLine = true;
            for(let el of this.paths){
                if(el.ids[0] === startName && el.ids[1] === endName){
                    signLine = false;
                    break;
                }
            }

            if(signLine){
                this.paths.push({
                    isChecked:this.inlineIsChecked,
                    id:startName+endName,
                    ids:[startName,endName],
                    path:nowLine
                });
                this.pathsOnlyName.push({
                    s:startName,
                    e:endName
                });
                this.drawLine();
            }

            function findToutch(arr){
                let nodes = this.nodes.filter(item=>{
                    return item.id !== startName && item.id !== endName;
                });
            
                let line1 = arr[0],
                    line2 = arr[1],
                    line3 = arr[2];
                
                let newLines = toutchFor.call(this);

                let cd = __DB__.get(endName).node.init.point.cd;
                if(newLines[2][1][0] > cd[0]){
                    line3[1] = [line3[1][0],line3[1][1]]
                    let line4 = [
                        newLines[2][1],
                        [cd[0],cd[1] + 10]
                    ];
                    let line5 = [
                        line4[1],
                        cd
                    ];
                    newLines.push(line4);
                    newLines.push(line5);
                }
            
                return newLines;
            
                function toutchFor(){
                    
                    for(let k in nodes){
                        let el = nodes[k];
                        let down = [el.node.init.point.d,el.node.init.point.c],
                            right = [el.node.init.point.b,el.node.init.point.c];
                        
                        let sgin_down = this.segmentsIntr(line3[0],line3[1],down[0],down[1]);
                        let sgin_right = this.segmentsIntr(line2[0],line2[1],right[0],right[1]);
                        
                        if(sgin_down){
                            touchDown.call(this,el.id)
                            break
                        }
            
                        if(sgin_right){
                            touchRight.call(this,el.id)
                            break
                        }
                        
                    }
            
                    return [line1,line2,line3];
                }
            
                function touchDown(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let c_the  = theDiv.node.init.point.c;
                    let cd_end = endDiv.node.init.point.cd;
            
                    line2 = [line2[0],[c_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], cd_end[1] +10]];
            
                    toutchFor.call(this);
                }

                function touchRight(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let b_the  = theDiv.node.init.point.b;
                    let cd_end = endDiv.node.init.point.cd;
            
                    line2 = [line2[0],[b_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], cd_end[1] +10]];

            
                    toutchFor.call(this);
                }
            }
        }

        // 自上而右下
        function next_x_t_y_d_l(){
            let lineSegments = [];

            let s = start.point.cd,
                e = end.point.ab;

            let x1 = s[0],
                y1 = s[1],
                x2 = e[0],
                y2 = e[1];
            
            let path1 = [s,[x1,y1 + 10]];
            let path2 = [path1[1],[x2,y1 + 10]];
            let path3 = [path2[1],e];

            lineSegments = [path1,path2,path3];
            lineSegments = findToutch.call(this,lineSegments);
            if(!lineSegments || lineSegments.length === 0)return;
            let nowLine = lineSegments.map(el=>{
                return {
                    x1:el[0][0],
                    y1:el[0][1],
                    x2:el[1][0],
                    y2:el[1][1],
                }
            });

            let signLine = true;
            for(let el of this.paths){
                if(el.ids[0] === startName && el.ids[1] === endName){
                    signLine = false;
                    break;
                }
            }

            if(signLine){
                this.paths.push({
                    isChecked:this.inlineIsChecked,
                    id:startName+endName,
                    ids:[startName,endName],
                    path:nowLine
                });
                this.pathsOnlyName.push({
                    s:startName,
                    e:endName
                });
        
                this.drawLine();
            }

            function findToutch(arr){
                let nodes = this.nodes.filter(item=>{
                    return item.id !== startName && item.id !== endName;
                });
            
                let newArr = JSON.stringify(arr);
                newArr = JSON.parse(newArr)

                let line1 = newArr[0],
                    line2 = newArr[1],
                    line3 = newArr[2];
                
                let newLines = toutchFor.call(this);
                let ab = __DB__.get(endName).node.init.point.ab;
                if(newLines[2][1][1] < ab[1]){
                    let line4 = [
                        newLines[2][1],
                        [ab[0],ab[1] - 10]
                    ];
                    let line5 = [
                        line4[1],
                        ab
                    ]
                    newLines.push(line4)
                    newLines.push(line5)
                }
            
                return newLines;
            
                function toutchFor(){
                    for(let k in nodes){
                        let el      = nodes[k];
                        let top     = [el.node.init.point.a,el.node.init.point.b],
                            left    = [el.node.init.point.a,el.node.init.point.d];
                        
                        let sgin_top  = this.segmentsIntr(line3[0],line3[1],top[0],top[1]);
                        let sgin_left = this.segmentsIntr(line2[0],line2[1],left[0],left[1]);
                        
                        if(sgin_top){
                            touchTop.call(this,el.id);
                            break;
                        }
            
                        if(sgin_left){
                            touchLeft.call(this,el.id)
                            break;
                        }
                        
                    }
            
                    return [line1,line2,line3];
                }
            
                function touchTop(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let a_the  = theDiv.node.init.point.a;
                    let ab_end = endDiv.node.init.point.ab;
            
                    line2 = [line2[0],[a_the[0] - 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], ab_end[1] - 10]];
            
                    toutchFor.call(this);
                }
            
                function touchLeft(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let d_the  = theDiv.node.init.point.d;
                    let ab_end = endDiv.node.init.point.ab;
                    
                    line2 = [line2[0],[d_the[0] - 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], ab_end[1] - 10]];
                    toutchFor.call(this);
                }
            }
        }

        // 自上而左下
        function next_x_t_y_d_r(){
            let lineSegments = [];

            let s = start.point.cd,
                e = end.point.ab;

            let x1 = s[0],
                y1 = s[1],
                x2 = e[0],
                y2 = e[1];
            
            let path1 = [s,[x1,y1 + 10]];
            let path2 = [path1[1],[x2,y1 + 10]];
            let path3 = [path2[1],e];

            lineSegments = [path1,path2,path3];
            lineSegments = findToutch.call(this,lineSegments);

            if(!lineSegments || lineSegments.length === 0)return;
            let nowLine = lineSegments.map(el=>{
                return {
                    x1:el[0][0],
                    y1:el[0][1],
                    x2:el[1][0],
                    y2:el[1][1],
                }
            });

            let signLine = true;
            for(let el of this.paths){
                if(el.ids[0] === startName && el.ids[1] === endName){
                    signLine = false;
                    break;
                }
            }

            if(signLine){
                this.paths.push({
                    isChecked:this.inlineIsChecked,
                    id:startName+endName,
                    ids:[startName,endName],
                    path:nowLine
                });
                this.pathsOnlyName.push({
                    s:startName,
                    e:endName
                });
        
                this.drawLine();
            }

            function findToutch(arr){
                let nodes = this.nodes.filter(item=>{
                    return item.id !== startName && item.id !== endName;
                });
            
                let line1 = arr[0],
                    line2 = arr[1],
                    line3 = arr[2];
                
                let newLines = toutchFor.call(this);
                let ab = __DB__.get(endName).node.init.point.ab;
                if(newLines[2][1][0] > ab[0]){
                    line3[1] = [line3[1][0],line3[1][1]]
                    let line4 = [
                        newLines[2][1],
                        [ab[0],ab[1] - 10]
                    ];
                    let line5 = [
                        line4[1],
                        ab
                    ]
                    newLines.push(line4)
                    newLines.push(line5)
                }
            
                return newLines;
            
                function toutchFor(){
                    for(let k in nodes){
                        let el      = nodes[k];
                        let top     = [el.node.init.point.a,el.node.init.point.b],
                            right   = [el.node.init.point.b,el.node.init.point.c];
                        
                        let sgin_top   = this.segmentsIntr(line3[0],line3[1],top[0],top[1]);
                        let sgin_right = this.segmentsIntr(line2[0],line2[1],right[0],right[1]);
                        
                        if(sgin_top){
                            touchTop.call(this,el.id);
                            break;
                        }
            
                        if(sgin_right){
                            touchRight.call(this,el.id)
                            break;
                        }
                        
                    }
            
                    return [line1,line2,line3];
                }
            
                function touchTop(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let b_the  = theDiv.node.init.point.b;
                    let ab_end = endDiv.node.init.point.ab;
            
                    line2 = [line2[0],[b_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], ab_end[1] - 10]];
            
                    toutchFor.call(this);
                }
            
                function touchRight(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let c_the  = theDiv.node.init.point.c;
                    let ab_end = endDiv.node.init.point.ab;
            
                    line2 = [line2[0],[c_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], ab_end[1] - 10]];
                    toutchFor.call(this);
                }
            }
        }

        // 自下而上
        function next_x_d_y_t_c(){
            let lineSegments = [];

            let s = start.point.ab,
                e = end.point.cd;

            let x1 = s[0],
                y1 = s[1],
                x2 = e[0],
                y2 = e[1];
            
            let path1 = [s,[x1,y1 - 10]];
            let path2 = [path1[1],[x2,y1 - 10]];
            let path3 = [path2[1],e];

            lineSegments = [path1,path2,path3];
            lineSegments = findToutch.call(this,lineSegments);

            if(!lineSegments || lineSegments.length === 0)return;
            let nowLine = lineSegments.map(el=>{
                return {
                    x1:el[0][0],
                    y1:el[0][1],
                    x2:el[1][0],
                    y2:el[1][1],
                }
            });

            let signLine = true;
            for(let el of this.paths){
                if(el.ids[0] === startName && el.ids[1] === endName){
                    signLine = false;
                    break;
                }
            }

            if(signLine){
                this.paths.push({
                    isChecked:this.inlineIsChecked,
                    ids:[startName,endName],
                    path:nowLine
                })

                this.pathsOnlyName.push({
                    s:startName,
                    e:endName
                });
                this.drawLine();
            }
            
            function findToutch(arr){

                let nodes = this.nodes.filter(item=>{
                    return item.id !== startName && item.id !== endName;
                });
            
                let line1 = arr[0],
                    line2 = arr[1],
                    line3 = arr[2],
                    line4 = [];
                
                let newLines = toutchFor.call(this);
            
                let cd = __DB__.get(endName).node.init.point.cd;
                if(newLines[2][1][0] > cd[0]){
                    line3[1] = [line3[1][0],line3[1][1]]
                    line4 = [
                        newLines[2][1],
                        [cd[0],cd[1] + 10]
                    ];
                    toutchFor.call(this,4)

                    let line5 = [
                        line4[1],
                        cd
                    ]
                    newLines.push(line4)
                    newLines.push(line5)
                }
            
                return newLines;
            
                function toutchFor(type){
                    for(let k in nodes){
                        let el = nodes[k];
                        let down = [el.node.init.point.d,el.node.init.point.c],
                            left = [el.node.init.point.a,el.node.init.point.d],
                            right = [el.node.init.point.b,el.node.init.point.c];
                        
                        let sgin_down  = this.segmentsIntr(line3[0],line3[1],down[0],down[1]);
                        let sgin_left  = this.segmentsIntr(line2[0],line2[1],left[0],left[1]);
                        
                        
                        if(sgin_down){
                            touchDown.call(this,el.id)
                            break
                        }
            
                        if(sgin_left){
                            touchLeft.call(this,el.id)
                            break
                        }

                        if(type === 4){
                            let sgin_right = this.segmentsIntr(line4[0],line4[1],right[0],right[1]);
                            if(sgin_right){
                                touchRight4.call(this,el.id)
                            }
                        }
                        
                    }
            
                    return [line1,line2,line3];
                }
            
                function touchDown(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let c_the  = theDiv.node.init.point.c;
                    let cd_end = endDiv.node.init.point.cd;
            
                    line2 = [line2[0],[c_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], cd_end[1] +10]];
            
                    toutchFor.call(this);
                }
            
                function touchLeft(id){
                    line1 = [
                        line1[0],
                        [line1[1][0],parseFloat(line1[1][1]) - 10]
                    ];
                    line2 = [
                        line1[1],
                        [line2[1][0], line2[1][1] - 10]
                    ];
                    line3 = [line2[1],line3[1]];
            
                    toutchFor.call(this);
                }

                function touchRight4(id){
                    let the = __DB__.get(id);
                    let c = the.node.init.point.c;
                    line3 = [line3[0],[line3[1][0],c[1] + 10]];
                    newLines[2] = line3;
                    line4 = [line3[1],[cd[0],c[1] + 10]];
                }
            }
        }
        
        // 自上而下
        function next_x_t_y_d_c(){
            let lineSegments = [];

            let s = start.point.cd,
                e = end.point.ab;

            let x1 = s[0],
                y1 = s[1],
                x2 = e[0],
                y2 = e[1];
            
            let path1 = [s,[x1,y1 + 10]];
            let path2 = [path1[1],[x2,y1 + 10]];
            let path3 = [path2[1],e];

            lineSegments = [path1,path2,path3];
            lineSegments = findToutch.call(this,lineSegments);
            

            if(!lineSegments || lineSegments.length === 0)return;
            let nowLine = lineSegments.map(el=>{
                return {
                    x1:el[0][0],
                    y1:el[0][1],
                    x2:el[1][0],
                    y2:el[1][1],
                }
            });

            let signLine = true;
            for(let eee of this.paths){
                if(eee.ids[0] === startName && eee.ids[1] === endName){
                    signLine = false;
                    break;
                }
            }

            if(signLine){
                this.paths.push({
                    isChecked:this.inlineIsChecked,
                    ids:[startName,endName],
                    path:nowLine
                })

                this.pathsOnlyName.push({
                    s:startName,
                    e:endName
                });
        
                this.drawLine();
            }
            
            function findToutch(arr){
                let nodes = this.nodes.filter(item=>{
                    return item.id !== startName && item.id !== endName;
                });

                let line1 = arr[0],
                    line2 = arr[1],
                    line3 = arr[2],
                    line4 = [];
                
                let newLines = toutchFor.call(this);
            
                let cd = __DB__.get(endName).node.init.point.ab;
                if(newLines[2][1][0] > cd[0]){
                    line3[1] = [line3[1][0],line3[1][1]]
                    line4 = [
                        newLines[2][1],
                        [cd[0],cd[1] - 10]
                    ];
                    toutchFor.call(this,4)

                    let line5 = [
                        line4[1],
                        cd
                    ]
                    newLines.push(line4)
                    newLines.push(line5)
                }
            
                return newLines;
            
                function toutchFor(type){
                    for(let k in nodes){
                        let el = nodes[k];
                        let down = [el.node.init.point.d,el.node.init.point.c],
                            left = [el.node.init.point.a,el.node.init.point.d],
                            right = [el.node.init.point.b,el.node.init.point.c];
                        
                        let sgin_down  = this.segmentsIntr(line3[0],line3[1],down[0],down[1]);
                        let sgin_left  = this.segmentsIntr(line2[0],line2[1],left[0],left[1]);

                        if(sgin_down){
                            touchDown.call(this,el.id)
                            break
                        }
            
                        if(sgin_left){
                            touchLeft.call(this,el.id)
                            break
                        }

                        if(type === 4){
                            let sgin_right = this.segmentsIntr(line4[0],line4[1],right[0],right[1]);
                            if(sgin_right){
                                touchRight4.call(this,el.id)
                            }
                        }
                        
                    }
            
                    return [line1,line2,line3];
                }
            
                function touchDown(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let c_the  = theDiv.node.init.point.c;
                    let cd_end = endDiv.node.init.point.ab;
            
                    line2 = [line2[0],[c_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], cd_end[1] -10]];
            
                    toutchFor.call(this);
                }
            
                function touchLeft(id){
                    line1 = [
                        line1[0],
                        [line1[1][0],parseFloat(line1[1][1]) - 10]
                    ];
                    line2 = [
                        line1[1],
                        [line2[1][0], line2[1][1] - 10]
                    ];
                    line3 = [line2[1],line3[1]];
            
                    toutchFor.call(this);
                }

                function touchRight4(id){
                    let the = ids[id];
                    let c = the.init.point.c;
                    line3 = [line3[0],[line3[1][0],c[1] + 10]];
                    newLines[2] = line3;
                    line4 = [line3[1],[cd[0],c[1] + 10]];
                }
            }
        }

        // 自左而右
        function next_x_l_y_r(){
            let lineSegments = [];

            let s = start.point.ab,
                e = end.point.ab;

            let x1 = s[0],
                y1 = s[1],
                x2 = e[0],
                y2 = e[1];
            
            let path1 = [s,[x1,y1 + 10]];
            let path2 = [path1[1],[x2,y1 + 10]];
            let path3 = [path2[1],e];

            lineSegments = [path1,path2,path3];
            lineSegments = findToutch.call(this,lineSegments);
            
            if(!lineSegments || lineSegments.length === 0)return;
            let arr = lineSegments.map(el=>{
                return {
                    x1:el[0][0],
                    y1:el[0][1],
                    x2:el[1][0],
                    y2:el[1][1],
                }
            });

            let signLine = true;
            for(let el of this.paths){
                if(el.ids[0] === startName && el.ids[1] === endName){
                    signLine = false;
                    break;
                }
            }

            if(signLine){
                this.paths.push({
                    isChecked:this.inlineIsChecked,
                    ids:[startName,endName],
                    path:arr
                })

                this.pathsOnlyName.push({
                    s:startName,
                    e:endName
                });
        
                this.drawLine();
            }
            
            function findToutch(arr){

                let nodes = this.nodes.filter(item=>{
                    return item.id !== startName && item.id !== endName;
                });
            
                let line1 = arr[0],
                    line2 = arr[1],
                    line3 = arr[2];
                
                let newLines = toutchFor.call(this);
            
                let cd = __DB__.get(endName).node.init.point.cd;
                if(newLines[2][1][0] > cd[0]){
                    line3[1] = [line3[1][0],line3[1][1]]
                    let line4 = [
                        newLines[2][1],
                        [cd[0],cd[1] + 10]
                    ];
                    let line5 = [
                        line4[1],
                        cd
                    ]
                    newLines.push(line4)
                    newLines.push(line5)
                }
            
                return newLines;
            
                function toutchFor(){
                    for(let k in nodes){
                        let el = nodes[k];
                        let down = [el.node.init.point.d,el.node.init.point.c],
                            left = [el.node.init.point.a,el.node.init.point.d];
                        
                        let sgin_down = this.segmentsIntr(line3[0],line3[1],down[0],down[1]);
                        let sgin_left = this.segmentsIntr(line2[0],line2[1],left[0],left[1]);
                        
                        if(sgin_down){
                            touchDown.call(this,el.id)
                            break
                        }
            
                        if(sgin_left){
                            touchLeft.call(this,el.id)
                            break
                        }
                        
                    }
            
                    return [line1,line2,line3];
                }
            
                function touchDown(id){
                    let theDiv = __DB__.get(id);
                    let endDiv = __DB__.get(endName);
                    let c_the  = theDiv.node.init.point.c;
                    let cd_end = endDiv.node.init.point.cd;
            
                    line2 = [line2[0],[c_the[0] + 10, line2[1][1]]];
                    line3 = [line2[1],[line2[1][0], cd_end[1] +10]];
            
                    toutchFor.call(this);
                }
            
                function touchLeft(id){
                    line1 = [
                        line1[0],
                        [line1[1][0],parseFloat(line1[1][1]) - 10]
                    ];
                    line2 = [
                        line1[1],
                        [line2[1][0], line2[1][1] - 10]
                    ];
                    line3 = [line2[1],line3[1]];
            
                    toutchFor.call(this);
                }
            }
        }

        // 自右而左
        function next_x_r_y_l(){
            next_x_l_y_r.call(this);
        }
    }

    // 画线
    drawLine(){
        if(this.paths.length === 0)return;
        this.canvas.innerHTML = "";

        let paths = JSON.stringify(this.paths);
        paths = JSON.parse(paths);

        let lineSize = __DB__.publicData.style.automaticLine.size;

        paths.map(item=>{
            item.color = item.isChecked?this.checkedColor:__DB__.publicData.style.automaticLine.color;
            return item;
        })

        let lineblack = paths.filter(item=>{
            return !item.isChecked;
        });
    
        let linered = paths.filter(item=>{
            return item.isChecked;
        });

        lineblack.forEach((item,i)=>{
            let html = '';
            item.path.forEach((el,i2)=>{
                html += `
                    <line 
                        x1="${el.x1}" 
                        y1="${el.y1}" 
                        x2="${el.x2}" 
                        y2="${el.y2}" 
                        stroke-dasharray="5,5" 
                        style="stroke:${item.color};stroke-width:${lineSize}"
                        marker-end='url(#markerArrow${item.ids[0]+item.ids[1]+(i2+1)})'
                        />
                `;
            })
            
            this.canvas.innerHTML += html;

            this.canvas.innerHTML += `
                <defs>
                    <marker style="overflow:visible" id='markerArrow${item.ids[0]+item.ids[1]+item.path.length}' markerWidth='12' markerHeight='12' refx='0' refy='0' orient='auto' viewBox="0 -15 30 30">
                        <path d='M-10,-5L0,0L-10,5' style='fill:orange' />
                    </marker>
                </defs>
            `;
        })
        //
        linered.forEach((item,i)=>{
            let html = '';
            item.path.forEach((el,i2)=>{
                html += `
                    <line 
                        x1="${el.x1}" 
                        y1="${el.y1}" 
                        x2="${el.x2}" 
                        y2="${el.y2}" 
                        stroke-dasharray="5,5"
                        style="stroke:${item.color};stroke-width:2"
                        marker-end='url(#markerArrow${item.ids[0]+item.ids[1]+(i2+1)})'
                        />
                `;
            })
            
            this.canvas.innerHTML += html;

            this.canvas.innerHTML += `
                <defs>
                    <marker style="overflow:visible" id='markerArrow${item.ids[0]+item.ids[1]+item.path.length}' markerWidth='12' markerHeight='12' refx='0' refy='0' orient='auto' viewBox="0 -15 30 30">
                        <path d='M-10,-5L0,0L-10,5' style='fill:orange' />
                    </marker>
                </defs>
            `;
        })

        
    }

    // 画引导线
    drawDirectionLine(res){
        let startNode = __DB__.get(res.id);
        let mid = startNode.node.init.point.mid;
        this.lineCanvas = document.getElementById("svgDirection");
        this.lineCanvas.parentNode.style.zIndex = 3;

        this.pull_isClick(false);

        let id = "guideLine1",
            x1 = mid[0],
            y1 = mid[1];
        document.onmousemove = (e)=>{
            let endEl = e.target.parentNode;
            let x = e.offsetX,
                y = e.offsetY;
            
            // 经过节点
            if(this.hasClass(endEl,'xmd-node')){
                let nodeId  = endEl.getAttribute('id');
                let node    = __DB__.get(nodeId);
                let poi     = node.node.init.poi;
                
                x = poi.x + e.offsetX;
                y = poi.y + e.offsetY;

                if(this.hasClass(e.target,'xmd-node-up')){
                    x = poi.x + e.offsetX;
                    y = poi.y - e.offsetY;
                }
                else if(this.hasClass(e.target,'xmd-node-down')){
                    let d = node.node.init.point.d;
                    x = d[0] + e.offsetX;
                    y = d[1] + e.offsetY;
                }
                
            }

            let line = `
                <line 
                    id="${id}" 
                    x1="${x1}" 
                    y1="${y1}" 
                    x2="${x}" 
                    y2="${y}" 
                    style="stroke:#1A67D2;stroke-width:2;z-index:10;" 
                    marker-end='url(#markerArrowguideLine1'
                    />
                <defs>
                    <marker style="overflow:visible" id='markerArrowguideLine1' markerWidth='12' markerHeight='12' refx='-5' refy='0' orient='auto' viewBox="0 -15 30 30">
                        <path d='M-10,-5L0,0L-10,5' style='fill:orange' />
                    </marker>
                </defs>
            `;
            this.lineCanvas.innerHTML = line;
        }

        document.onmousedown = (e)=>{
            document.onmousemove = null;
            document.onmousedown = null;
            

            this.lineCanvas.parentNode.style.zIndex = 1;
            this.lineCanvas.innerHTML = "";
            
        }
    }

    pull_isClick(type=true){
        let pullEls = document.querySelectorAll('.xmd-node-pull');
        for(let el of pullEls){
            let eles = el.childNodes
            for(let ele of eles){
                ele.style.pointerEvents = type?'auto':'none';
            }
        }
    }

    // 取消引导线
    cancelDirectionLine(){
        // this.startId = "";
        document.onmousemove = null;
        document.onmousedown = null;
        this.isDraw     = false;
        
        this.lineCanvas = document.getElementById("svgDirection");
        this.lineCanvas.innerHTML = "";
        this.pull_isClick();
    }

    // 显示某条线
    showLine(s,e){
        for(let el of this.pathsOnlyName){
            if(el.s === s && el.e === e){
                el.isChecked = true;
                break;
            }
        }

        this.checkedColor = __DB__.publicData.style.automaticLine.colorChecked;

        this.reset({
            nodes:this.nodes
        });
        
    }

    // 隐藏所有线
    hideLineAll(){
        for(let el of this.pathsOnlyName){
            el.isChecked = false;
        }

        this.checkedColor = __DB__.publicData.style.automaticLine.color;

        this.reset({
            nodes:this.nodes
        });
    }

    // 选中某条线
    checkedLine(s,e){
        for(let el of this.pathsOnlyName){
            el.isChecked = false;
        }
        for(let el of this.pathsOnlyName){
            if(el.s === s && el.e === e){
                el.isChecked = true;
                break;
            }
        }

        this.reset({
            nodes:this.nodes
        });
        
    }

    // 查找相交线
    segmentsIntr(a,b,c,d){
        a = {x:parseInt(a[0]),y:parseInt(a[1])};
        b = {x:parseInt(b[0]),y:parseInt(b[1])};
        c = {x:parseInt(c[0]),y:parseInt(c[1])};
        d = {x:parseInt(d[0]),y:parseInt(d[1])};

        /** 1 解线性方程组, 求线段交点. **/  
        // 如果分母为0 则平行或共线, 不相交  
        var denominator = (b.y - a.y)*(d.x - c.x) - (a.x - b.x)*(c.y - d.y);  
        if (denominator==0) {  
            return false;  
        }  
        
        // 线段所在直线的交点坐标 (x , y)      
        var x = ( (b.x - a.x) * (d.x - c.x) * (c.y - a.y)   
                    + (b.y - a.y) * (d.x - c.x) * a.x   
                    - (d.y - c.y) * (b.x - a.x) * c.x ) / denominator ;  
        var y = -( (b.y - a.y) * (d.y - c.y) * (c.x - a.x)   
                    + (b.x - a.x) * (d.y - c.y) * a.y   
                    - (d.x - c.x) * (b.y - a.y) * c.y ) / denominator;  
        
        /** 2 判断交点是否在两条线段上 **/  
        if (  
            // 交点在线段1上  
            (x - a.x) * (x - b.x) <= 0 && (y - a.y) * (y - b.y) <= 0  
            // 且交点也在线段2上  
            && (x - c.x) * (x - d.x) <= 0 && (y - c.y) * (y - d.y) <= 0  
            ){  
    
            // 返回交点p  
            return {  
                    x :  x,  
                    y :  y  
                }  
        }  
        //否则不相交  
        return false  
    }

    hasClass(ele, cls) {
        if (ele) {
          cls = cls || ''
          if (cls.replace(/\s/g, '').length == 0) return false // 当cls没有参数时，返回false
          return new RegExp(' ' + cls + ' ').test(' ' + ele.className + ' ')
        }
    }

    // 清空关联线
    clear(){
        this.lineCanvas = document.getElementById("svgDirection");
        if(this.lineCanvas)this.lineCanvas.innerHTML = "";
        if(this.canvas)this.canvas.innerHTML = "";
        this.paths = [];
        this.pathsOnlyName = [];
    }

    // 使用
    use(){
        this.reset({nodes:__DB__.getAllNodes()})
    }
}

let automatic = new automaticClass();
export default automatic;